/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.common.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyResourceConfigurer;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.PropertiesLoaderSupport;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Properties;

/**
 * Spring 参数获取工具类
 * <p>
 *
 * @author yoara
 */
@Component
public class SpringPropertyReader implements BeanFactoryPostProcessor{
    private final static Logger logger = LoggerFactory.getLogger(SpringPropertyReader.class);

    private static Environment env;

    private static Properties properties=new Properties();

    public static void setProperties(String key, String value){
        properties.put(key, value);
    }

    public static String getProperty(String propertyName){
        return getProperty(propertyName, null);
    }

    public static String getProperty(String propertyName, String defValue){
        String val = properties.getProperty(propertyName);
        if(StringUtils.hasText(val)){
            return val;
        }
        if(env==null){
            env = SpringBeanPicker.getBean(Environment.class);
        }
        val = env.getProperty(propertyName);
        if(StringUtils.hasText(val)){
            return val;
        }
        return defValue;
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            // get the names of BeanFactoryPostProcessor
            String[] postProcessorNames = beanFactory
                    .getBeanNamesForType(PropertiesLoaderSupport.class, true, false);

            for (String ppName : postProcessorNames) {
                // get the specified PropertiesLoaderSupport
                PropertiesLoaderSupport beanProcessor =
                        beanFactory.getBean(ppName, PropertiesLoaderSupport.class);

                // get the method mergeProperties
                // in class PropertiesLoaderSupport
                Method mergeProperties = PropertiesLoaderSupport.class.
                        getDeclaredMethod("mergeProperties");
                // get the props
                mergeProperties.setAccessible(true);
                Properties props = (Properties) mergeProperties.invoke(beanProcessor);

                // get the method convertProperties
                // in class PropertyResourceConfigurer
                if(beanProcessor instanceof PropertyResourceConfigurer){
                    Method convertProperties = PropertyResourceConfigurer.class.
                            getDeclaredMethod("convertProperties", Properties.class);
                    // convert properties
                    convertProperties.setAccessible(true);
                    convertProperties.invoke(beanProcessor, props);
                }
                properties.putAll(System.getProperties());
                properties.putAll(props);
            }
        }catch(Exception e){
            logger.error(e.getMessage(),e);
        }
    }
}